﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using QUT.Bio.Util;

namespace QUT.Bio.Graphs {
	/// <summary>
	///	An EdgeCollection is a SparseMatrix of objects provides a lookup table yielding a connection (if it exists)
	/// between two edges. Node Id values are used to identify edges. Edges are directed, but that may change in the future.
	/// </summary>
	/// <typeparam name="NodeType">The Id type of the edges connected by this graph.</typeparam>

	public class EdgeCollection<NodeType> : SparseMatrix<NodeType, NodeType, object>
	{}

/*
		/// <summary>
		/// Indexer yielding the edge connecting edges identified by fromID and toId. Returns null if there is no such edge.
		/// </summary>
		/// <param name="fromId">The id of the source node.</param>
		/// <param name="toId">The id of the destination node.</param>
		/// <returns>The edge connecting fromId to toId, or null if not present.</returns>
		
		public new Edge<NodeType, EdgeContentType> this[NodeType fromId, NodeType toId] {
			get {
				try {
					return base[fromId, toId];
				}
				catch {
					return default(EdgeContentType);
				}
			}
			set {
				if ( ! edges.ContainsKey( value.FromId ) ) {
					edges[value.FromId] = new Dictionary<NodeType, Edge<NodeType, EdgeContentType>>();
				}

				edges[value.FromId][value.ToId] = value;
			}
		}
		
		/// <summary>
		/// Adds a sequence of edges to the collection, then (in the event that at least one edge was added) triggers the CollectionChanged event.
		/// </summary>
		/// <param name="newEdges">A sequence of edges to add to the collection.</param>
		/// <exception cref="System.NullReferenceException">NullReferenceException if newEdges is null.</exception>
		
		public void AddRange( IEnumerable<Edge<NodeType, EdgeContentType>> newEdges ) {
			bool changed = false;
			
			foreach ( Edge<NodeType, EdgeContentType> arc in newEdges ) {
				this[arc.FromId, arc.ToId] = arc;
				changed = true;
			}
			
			if ( changed ) {
				SignalCollectionChanged();
			}
		}

		/// <summary>
		/// If the collection contains some edges, removes all edges from this collection,
		/// then fires the CollectionChanged event.
		/// </summary>
		
		public void Clear() {
			if ( edges.Count > 0 ) {
				edges.Clear();
				SignalCollectionChanged();
			}
		}

		/// <summary>
		/// Determines if the collection contains an edge connecting two edges.
		/// </summary>
		/// <param name="fromId">The id of the source node.</param>
		/// <param name="toId">The id of the destination node.</param>
		/// <returns>True iff the collection contains an edge connecting edges with ids fromId and toId.</returns>

		public bool ContainsEdge( NodeType fromId, NodeType toId ) {
			return edges.ContainsKey( fromId ) && edges[fromId].ContainsKey( toId );
		}

		/// <summary>
		/// Gets an enumerator that iterates over all edges in the collection.
		/// </summary>
		/// <returns>An enumerator that iterates over all edges in the collection.</returns>
		
		public IEnumerator<Edge<NodeType, EdgeContentType>> GetEnumerator() {
			foreach ( var x in edges ) {
				foreach ( var y in x.Value ) {
					yield return y.Value;
				}
			}
		}

		/// <summary>
		/// Gets an enumerator that iterates over all edges in the collection.
		/// </summary>
		/// <returns>An enumerator that iterates over all edges in the collection.</returns>

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
			foreach ( var x in edges ) {
				foreach ( var y in x.Value ) {
					yield return y.Value;
				}
			}
		}

		/// <summary>
		/// Removes a node from the collection.
		/// </summary>
		/// <param name="node">The node to be removed.</param>
		/// <exception cref="System.ArgumentNullException">The node is null or its Id is null.</exception>

		public void Remove ( NodeType fromId, NodeType toId ) {
			if ( edges.ContainsKey( fromId ) ) {
				Dictionary<NodeType, Edge<NodeType, EdgeContentType>> e2 = edges[edge.
				&& edges[FromId].ContainsKey( edge.ToId ) ) {
				edges[FromId].Remove( edge.Id );
				
				if ( edges[
		}

		/// <summary>
		/// Removes all edges that match a supplied predicate from the collection.
		/// </summary>
		/// <param name="where">A predicate used to filter out edges.</param>
		/// <exception cref="System.ArgumentNullException">The node is null or its Id is null.</exception>

		public void RemoveAll ( Predicate<Node<NodeType, EdgeContentType>> where ) {
			Node<NodeType, EdgeContentType>[] existingNodes = edges.Values.ToArray();
			bool changed = false;

			foreach ( var node in existingNodes ) {
				if ( where( node ) ) {
					edges.Remove( node.Id );
					changed = true;
				}
			}

			if ( changed ) {
				SignalCollectionChanged();
			}
		}

		/// <summary>
		/// Replaces the contents of the collection with a sequence of edges to the collection, then triggers the CollectionChanged event.
		/// <para>This is basically the same as Clear() followed by AddRange, except we only fire CollectionChanged once.</para>
		/// </summary>
		/// <param name="newEdges"></param>
		/// <exception cref="System.ArgumentNullException">newEdges is null or one of the node ids is null</exception>
		/// <exception cref="System.ArgumentException">The sequence of edges to be added contains a node with the same Id as one already present in the collection.</exception>

		public void ReplaceAll ( IEnumerable<Node<NodeType, EdgeContentType>> newNodes ) {
			bool changed = false;

			if ( edges.Count > 0 ) {
				edges.Clear();
				changed = true;
			}

			foreach ( var node in newNodes ) {
				edges.Add( node.Id, node );
				changed = true;
			}

			if ( changed ) {
				SignalCollectionChanged();
			}
		}

		/// <summary>
		/// Removes all items matching the supplied predicate, then adds all items in a sequence of edges, and finally (if something changed) triggers the Collectionchanged event.
		/// <para>This is basically the same as RemoveAll( where ) followed by AddRange, except we only fire CollectionChanged once.</para>
		/// </summary>
		/// <param name="newEdges">A sequence of edges to be added to the collection.</param>
		/// <param name="where">A predicate used to filter out unwnated edges.</param>
		/// <exception cref="System.ArgumentNullException">newEdges is null or one of the node ids is null</exception>
		/// <exception cref="System.ArgumentException">The sequence of edges to be added contains a node with the same Id as one already present in the collection.</exception>

		public void ReplaceAll (
			IEnumerable<Edge<NodeType, EdgeContentType>> newEdges,
			Predicate<Edge<NodeType, EdgeContentType>> where
		) {
			Edge<NodeType, EdgeContentType>[] existingEdges = edges.Values.ToArray();
			bool changed = false;

			foreach ( var edge in existingEdges ) {
				if ( where( edge ) ) {
					edges.Remove( edge.Id );
					changed = true;
				}
			}

			foreach ( var node in newEdges ) {
				edges[node.Id, node );
				changed = true;
			}

			if ( changed ) {
				SignalCollectionChanged();
			}
		}
		
		/// <summary>
		/// Triggers the CollectionChanged event.
		/// </summary>
		
		private void SignalCollectionChanged () {
			if ( CollectionChanged != null ) {
				CollectionChanged( this );
			}
		}
	}
 */
 
}
